package mdm.led.log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import mdm.led.common.AjaxResponse;
import mdm.led.dao.SysLogMapper;
import mdm.led.entity.SysLog;
import mdm.led.util.IPUtil;
import mdm.led.util.session.TokenUtil;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;

/**
 * 记录操作日志
 */
@Aspect
@Component
public class LogAop {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAop.class);

    private final SysLogMapper sysLogMapper;

    @Autowired
    public LogAop(SysLogMapper sysLogMapper) {
        this.sysLogMapper = sysLogMapper;
    }

    @Pointcut("execution(public * mdm.led..controller..*.*(..))")
    private void method() {
    }

    @AfterReturning(value = "method()", returning = "response")  // 使用上面定义的切入点
    public void recordLog(JoinPoint joinPoint, AjaxResponse response) {
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operationModule;
            String operationFunction;
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length
                            && method.getAnnotation(OperationLog.class) != null
                            && response.getStatus() == 100) {
                        operationModule = method.getAnnotation(OperationLog.class).operationModule();
                        operationFunction = method.getAnnotation(OperationLog.class).operationFunction();

                        SysLog log = new SysLog();
                        log.setcOperatorModule(operationModule);
                        log.setcOperatorFunction(operationFunction);
                        //操作用户
                        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                        String token;
                        if (response.getResult() != null && response.getResult() instanceof JSONObject
                                && JSONObject.parseObject(JSON.toJSONString(response.getResult())).get("token") != null) {
                            //针对登录
                            token = JSONObject.parseObject(JSON.toJSONString(response.getResult())).get("token").toString();
                            log.setcUserId(TokenUtil.getUserId(token));
                        } else if (response.getResult() != null && response.getResult() instanceof JSONObject
                                && JSONObject.parseObject(JSON.toJSONString(response.getResult())).get("userId") != null) {
                            //针对登出
                            log.setcUserId(Integer.valueOf(JSONObject.parseObject(JSON.toJSONString(response.getResult())).get("userId").toString()));
                        } else {
                            //后期验证登录时需要加上
                            token = TokenUtil.getToken(request);
                            log.setcUserId(TokenUtil.getUserId(token));
                        }

                        log.setcIp(IPUtil.getIp(request));

                        log.setcOperatorTime(new Timestamp(System.currentTimeMillis()));
                        sysLogMapper.insertSelective(log);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("log record failed", e);
        }
    }
}
